package com.ss.web.tagmark.init;

import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import com.ss.web.tagmark.service.UserService;

/**
 * Spring Security方面的配置
 *
 * @author Administrator
 *
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
	@Autowired
	private UserService userService;

	@Autowired
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userService).passwordEncoder(new WebSecurityPasswordEncoder());
	}

	private static AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> customAuthenticationDetailsSource() {
		return new SecurityAuthenticationDetailsSource();
	}

	public AnonymousAuthenticationFilter customAnonymousFilter() {
		AnonymousAuthenticationFilter filter = new AnonymousAuthenticationFilter(UUID.randomUUID().toString());
		filter.setAuthenticationDetailsSource(customAuthenticationDetailsSource());
		return filter;
	}

	private AccessDecisionManager customAccessDecisionManager() {
		return new WebSecurityAccessDecisionManager();
	}

	@Configuration
	@Order(1)
	public class LoginWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
		protected void configure(HttpSecurity http) throws Exception {
			// 只拦截登录相关的操作
			http.requestMatcher(WebSecurityRequestMatcher.getMatcherInstance("/login", "/login-error"))
					.authorizeRequests().antMatchers("/**").authenticated()
					.accessDecisionManager(customAccessDecisionManager())
					//
					.and().anonymous()
					//
					.and().formLogin().disable()
					//
					.rememberMe().alwaysRemember(true).key("tag_system").rememberMeCookieName("_tag_sys_ck_")
					.tokenValiditySeconds(3600).userDetailsService(userService)
					//
					.and().anonymous().authenticationFilter(customAnonymousFilter())
					//
					.and().headers().disable();
		}
	}

	@Configuration
	@Order(10)
	public class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
		@Override
		protected void configure(HttpSecurity http) throws Exception {
			//
			http.authorizeRequests().anyRequest().authenticated().accessDecisionManager(customAccessDecisionManager())
					//
					.and().formLogin().authenticationDetailsSource(customAuthenticationDetailsSource())
					.loginPage("/login").loginProcessingUrl("/logon").failureUrl("/login-error")
					.defaultSuccessUrl("/", false).permitAll()
					//
					.and().logout().logoutSuccessUrl("/").permitAll()
					//
					.and().exceptionHandling().accessDeniedPage("/error/403")
					//
					.and().rememberMe().alwaysRemember(true).key("tag_system").rememberMeCookieName("_tag_sys_ck_")
					.tokenValiditySeconds(3600).userDetailsService(userService)
					//
					.and().anonymous().authenticationFilter(customAnonymousFilter()).disable()
					//
					.headers().disable();

			http.csrf().requireCsrfProtectionMatcher(new DefaultRequiresCsrfMatcher()).disable();// 把ajax请求放开
		}

		public void configure(WebSecurity web) throws Exception {
			// 解决静态资源被拦截的问题
			web.ignoring().antMatchers("/js/**", "/css/**", "/images/**", "/fonts/**", "/error", "/favicon.ico");
		}
	}
}